Proper connect_port
[juce-lv2.git] / juce / source / extras / audio plugins / demo / Source / PluginProcessor.cpp
blob50356489cae426c08ba3400fc9697d1930b9ddfb
1 /*
2 ==============================================================================
4 This file was auto-generated by the Jucer!
6 It contains the basic startup code for a Juce application.
8 ==============================================================================
9 */
11 #include "PluginProcessor.h"
12 #include "PluginEditor.h"
14 //==============================================================================
15 /** A demo synth sound that's just a basic sine wave.. */
16 class SineWaveSound : public SynthesiserSound
18 public:
19 SineWaveSound()
23 bool appliesToNote (const int /*midiNoteNumber*/) { return true; }
24 bool appliesToChannel (const int /*midiChannel*/) { return true; }
27 //==============================================================================
28 /** A simple demo synth voice that just plays a sine wave.. */
29 class SineWaveVoice : public SynthesiserVoice
31 public:
32 SineWaveVoice()
33 : angleDelta (0.0),
34 tailOff (0.0)
38 bool canPlaySound (SynthesiserSound* sound)
40 return dynamic_cast <SineWaveSound*> (sound) != 0;
43 void startNote (const int midiNoteNumber, const float velocity,
44 SynthesiserSound* /*sound*/, const int /*currentPitchWheelPosition*/)
46 currentAngle = 0.0;
47 level = velocity * 0.15;
48 tailOff = 0.0;
50 double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
51 double cyclesPerSample = cyclesPerSecond / getSampleRate();
53 angleDelta = cyclesPerSample * 2.0 * double_Pi;
56 void stopNote (const bool allowTailOff)
58 if (allowTailOff)
60 // start a tail-off by setting this flag. The render callback will pick up on
61 // this and do a fade out, calling clearCurrentNote() when it's finished.
63 if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
64 // stopNote method could be called more than once.
65 tailOff = 1.0;
67 else
69 // we're being told to stop playing immediately, so reset everything..
71 clearCurrentNote();
72 angleDelta = 0.0;
76 void pitchWheelMoved (const int /*newValue*/)
78 // can't be bothered implementing this for the demo!
81 void controllerMoved (const int /*controllerNumber*/, const int /*newValue*/)
83 // not interested in controllers in this case.
86 void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
88 if (angleDelta != 0.0)
90 if (tailOff > 0)
92 while (--numSamples >= 0)
94 const float currentSample = (float) (sin (currentAngle) * level * tailOff);
96 for (int i = outputBuffer.getNumChannels(); --i >= 0;)
97 *outputBuffer.getSampleData (i, startSample) += currentSample;
99 currentAngle += angleDelta;
100 ++startSample;
102 tailOff *= 0.99;
104 if (tailOff <= 0.005)
106 clearCurrentNote();
108 angleDelta = 0.0;
109 break;
113 else
115 while (--numSamples >= 0)
117 const float currentSample = (float) (sin (currentAngle) * level);
119 for (int i = outputBuffer.getNumChannels(); --i >= 0;)
120 *outputBuffer.getSampleData (i, startSample) += currentSample;
122 currentAngle += angleDelta;
123 ++startSample;
129 private:
130 double currentAngle, angleDelta, level, tailOff;
134 //==============================================================================
135 JuceDemoPluginAudioProcessor::JuceDemoPluginAudioProcessor()
136 : delayBuffer (2, 12000)
138 // Set up some default values..
139 gain = 1.0f;
140 delay = 0.5f;
142 lastUIWidth = 400;
143 lastUIHeight = 200;
145 lastPosInfo.resetToDefault();
146 delayPosition = 0;
148 // Initialise the synth...
149 for (int i = 4; --i >= 0;)
150 synth.addVoice (new SineWaveVoice()); // These voices will play our custom sine-wave sounds..
152 synth.addSound (new SineWaveSound());
155 JuceDemoPluginAudioProcessor::~JuceDemoPluginAudioProcessor()
159 //==============================================================================
160 int JuceDemoPluginAudioProcessor::getNumParameters()
162 return totalNumParams;
165 float JuceDemoPluginAudioProcessor::getParameter (int index)
167 // This method will be called by the host, probably on the audio thread, so
168 // it's absolutely time-critical. Don't use critical sections or anything
169 // UI-related, or anything at all that may block in any way!
170 switch (index)
172 case gainParam: return gain;
173 case delayParam: return delay;
174 default: return 0.0f;
178 void JuceDemoPluginAudioProcessor::setParameter (int index, float newValue)
180 // This method will be called by the host, probably on the audio thread, so
181 // it's absolutely time-critical. Don't use critical sections or anything
182 // UI-related, or anything at all that may block in any way!
183 switch (index)
185 case gainParam: gain = newValue; break;
186 case delayParam: delay = newValue; break;
187 default: break;
191 const String JuceDemoPluginAudioProcessor::getParameterName (int index)
193 switch (index)
195 case gainParam: return "gain";
196 case delayParam: return "delay";
197 default: break;
200 return String::empty;
203 const String JuceDemoPluginAudioProcessor::getParameterText (int index)
205 return String (getParameter (index), 2);
208 //==============================================================================
209 void JuceDemoPluginAudioProcessor::prepareToPlay (double sampleRate, int /*samplesPerBlock*/)
211 // Use this method as the place to do any pre-playback
212 // initialisation that you need..
213 synth.setCurrentPlaybackSampleRate (sampleRate);
214 keyboardState.reset();
215 delayBuffer.clear();
218 void JuceDemoPluginAudioProcessor::releaseResources()
220 // When playback stops, you can use this as an opportunity to free up any
221 // spare memory, etc.
222 keyboardState.reset();
225 void JuceDemoPluginAudioProcessor::reset()
227 // Use this method as the place to clear any delay lines, buffers, etc, as it
228 // means there's been a break in the audio's continuity.
229 delayBuffer.clear();
232 void JuceDemoPluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
234 const int numSamples = buffer.getNumSamples();
235 int channel, dp = 0;
237 // Go through the incoming data, and apply our gain to it...
238 for (channel = 0; channel < getNumInputChannels(); ++channel)
239 buffer.applyGain (channel, 0, buffer.getNumSamples(), gain);
241 // Now pass any incoming midi messages to our keyboard state object, and let it
242 // add messages to the buffer if the user is clicking on the on-screen keys
243 keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);
245 // and now get the synth to process these midi events and generate its output.
246 synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
248 // Apply our delay effect to the new output..
249 for (channel = 0; channel < getNumInputChannels(); ++channel)
251 float* channelData = buffer.getSampleData (channel);
252 float* delayData = delayBuffer.getSampleData (jmin (channel, delayBuffer.getNumChannels() - 1));
253 dp = delayPosition;
255 for (int i = 0; i < numSamples; ++i)
257 const float in = channelData[i];
258 channelData[i] += delayData[dp];
259 delayData[dp] = (delayData[dp] + in) * delay;
260 if (++dp > delayBuffer.getNumSamples())
261 dp = 0;
265 delayPosition = dp;
267 // In case we have more outputs than inputs, we'll clear any output
268 // channels that didn't contain input data, (because these aren't
269 // guaranteed to be empty - they may contain garbage).
270 for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
271 buffer.clear (i, 0, buffer.getNumSamples());
273 // ask the host for the current time so we can display it...
274 AudioPlayHead::CurrentPositionInfo newTime;
276 if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition (newTime))
278 // Successfully got the current time from the host..
279 lastPosInfo = newTime;
281 else
283 // If the host fails to fill-in the current time, we'll just clear it to a default..
284 lastPosInfo.resetToDefault();
288 //==============================================================================
289 AudioProcessorEditor* JuceDemoPluginAudioProcessor::createEditor()
291 return new JuceDemoPluginAudioProcessorEditor (this);
294 //==============================================================================
295 void JuceDemoPluginAudioProcessor::getStateInformation (MemoryBlock& destData)
297 // You should use this method to store your parameters in the memory block.
298 // Here's an example of how you can use XML to make it easy and more robust:
300 // Create an outer XML element..
301 XmlElement xml ("MYPLUGINSETTINGS");
303 // add some attributes to it..
304 xml.setAttribute ("uiWidth", lastUIWidth);
305 xml.setAttribute ("uiHeight", lastUIHeight);
306 xml.setAttribute ("gain", gain);
307 xml.setAttribute ("delay", delay);
309 // then use this helper function to stuff it into the binary blob and return it..
310 copyXmlToBinary (xml, destData);
313 void JuceDemoPluginAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
315 // You should use this method to restore your parameters from this memory block,
316 // whose contents will have been created by the getStateInformation() call.
318 // This getXmlFromBinary() helper function retrieves our XML from the binary blob..
319 ScopedPointer<XmlElement> xmlState (getXmlFromBinary (data, sizeInBytes));
321 if (xmlState != 0)
323 // make sure that it's actually our type of XML object..
324 if (xmlState->hasTagName ("MYPLUGINSETTINGS"))
326 // ok, now pull out our parameters..
327 lastUIWidth = xmlState->getIntAttribute ("uiWidth", lastUIWidth);
328 lastUIHeight = xmlState->getIntAttribute ("uiHeight", lastUIHeight);
330 gain = (float) xmlState->getDoubleAttribute ("gain", gain);
331 delay = (float) xmlState->getDoubleAttribute ("delay", delay);
336 const String JuceDemoPluginAudioProcessor::getInputChannelName (const int channelIndex) const
338 return String (channelIndex + 1);
341 const String JuceDemoPluginAudioProcessor::getOutputChannelName (const int channelIndex) const
343 return String (channelIndex + 1);
346 bool JuceDemoPluginAudioProcessor::isInputChannelStereoPair (int /*index*/) const
348 return true;
351 bool JuceDemoPluginAudioProcessor::isOutputChannelStereoPair (int /*index*/) const
353 return true;
356 bool JuceDemoPluginAudioProcessor::acceptsMidi() const
358 #if JucePlugin_WantsMidiInput
359 return true;
360 #else
361 return false;
362 #endif
365 bool JuceDemoPluginAudioProcessor::producesMidi() const
367 #if JucePlugin_ProducesMidiOutput
368 return true;
369 #else
370 return false;
371 #endif
374 //==============================================================================
375 // This creates new instances of the plugin..
376 AudioProcessor* JUCE_CALLTYPE createPluginFilter()
378 return new JuceDemoPluginAudioProcessor();